//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package roadmap_content_api_serv

import (
	"context"

	"atomgit.com/openlinksaas-org/api-server/admin_api_serv/admin_common"
	"atomgit.com/openlinksaas-org/api-server/dao"
	"atomgit.com/openlinksaas-org/api-server/dao/roadmap_dao"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/admin_auth_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/roadmap_api"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/roadmap_content_api"
	"go.mongodb.org/mongo-driver/mongo"
)

func (apiImpl *RoadmapContentApiImpl) AddEdge(ctx context.Context, req *roadmap_content_api.AddEdgeRequest) (*roadmap_content_api.AddEdgeResponse, error) {
	ownerType := roadmap_api.ROADMAP_OWNER_TYPE_ROADMAP_OWNER_ADMIN
	ownerUserId := ""
	var roadmapPerm *admin_auth_api.RoadmapPerm
	isWhiteUser := false

	userSess, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if ok {
		ownerType = roadmap_api.ROADMAP_OWNER_TYPE_ROADMAP_OWNER_USER
		ownerUserId = userSess.UserId
		exist, err := roadmap_dao.WhiteUserDao.Exist(ctx, userSess.UserId)
		if err != nil {
			return nil, err
		}
		isWhiteUser = exist
	} else {
		adminSess, ok := dao.CacheDao.GetAdminSession(ctx, req.SessionId)
		if !ok {
			return &roadmap_content_api.AddEdgeResponse{
				Code:   roadmap_content_api.AddEdgeResponse_CODE_WRONG_SESSION,
				ErrMsg: "会话不存在",
			}, nil
		}
		if !adminSess.AuthOk {
			return &roadmap_content_api.AddEdgeResponse{
				Code:   roadmap_content_api.AddEdgeResponse_CODE_NOT_AUTH,
				ErrMsg: "未授权会话",
			}, nil
		}
		adminUserCfg, err := admin_common.GetAdminUserConfig(ctx, apiImpl.adminCfg, adminSess.UserName)
		if err != nil {
			return nil, err
		}
		if !adminUserCfg.PermInfo.RoadmapPerm.Read {
			return &roadmap_content_api.AddEdgeResponse{
				Code:   roadmap_content_api.AddEdgeResponse_CODE_NO_PERMISSION,
				ErrMsg: "没有权限",
			}, nil
		}
		ownerType = roadmap_api.ROADMAP_OWNER_TYPE_ROADMAP_OWNER_ADMIN
		ownerUserId = adminSess.UserName
		roadmapPerm = adminUserCfg.PermInfo.RoadmapPerm
	}

	roadmapItem, err := roadmap_dao.RoadmapInfoDao.Get(ctx, req.EdgeKey.RoadmapId)
	if err != nil {
		return &roadmap_content_api.AddEdgeResponse{
			Code:   roadmap_content_api.AddEdgeResponse_CODE_NO_ROADMAP,
			ErrMsg: "路线图不存在",
		}, nil
	}
	userPerm := apiImpl.calcUserPerm(roadmapItem, ownerType, ownerUserId, roadmapPerm, isWhiteUser)
	if !userPerm.CanUpdateContent {
		return &roadmap_content_api.AddEdgeResponse{
			Code:   roadmap_content_api.AddEdgeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	//检查节点是否存在
	exist, err := roadmap_dao.NodeDao.Exist(ctx, req.EdgeKey.RoadmapId, req.EdgeKey.FromNodeId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &roadmap_content_api.AddEdgeResponse{
			Code:   roadmap_content_api.AddEdgeResponse_CODE_NO_FROM_NODE,
			ErrMsg: "起始节点不存在",
		}, nil
	}
	exist, err = roadmap_dao.NodeDao.Exist(ctx, req.EdgeKey.RoadmapId, req.EdgeKey.ToNodeId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &roadmap_content_api.AddEdgeResponse{
			Code:   roadmap_content_api.AddEdgeResponse_CODE_NO_FROM_NODE,
			ErrMsg: "结束节点不存在",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = roadmap_dao.EdgeDao.Upsert(sessCtx, &roadmap_dao.EdgeInfoDbItem{
			RoadmapId: req.EdgeKey.RoadmapId,
			EdgeKey: roadmap_dao.EdgeKeyDbItem{
				FromNodeId:   req.EdgeKey.FromNodeId,
				FromHandleId: req.EdgeKey.FromHandleId,
				ToNodeId:     req.EdgeKey.ToNodeId,
				ToHandleId:   req.EdgeKey.ToHandleId,
			},
			BasicInfo: roadmap_dao.BasicEdgeInfoDbItem{
				EdgeType:      uint32(req.BasicInfo.EdgeType),
				EdgeColor:     req.BasicInfo.EdgeColor,
				HasBeginArrow: req.BasicInfo.HasBeginArrow,
				HasEndArrow:   req.BasicInfo.HasEndArrow,
				EdgeWidth:     req.BasicInfo.EdgeWidth,
			},
		})
		if err != nil {
			return nil, err
		}
		return &roadmap_content_api.AddEdgeResponse{
			Code: roadmap_content_api.AddEdgeResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*roadmap_content_api.AddEdgeResponse), nil
}

func (apiImpl *RoadmapContentApiImpl) ListEdge(ctx context.Context, req *roadmap_content_api.ListEdgeRequest) (*roadmap_content_api.ListEdgeResponse, error) {
	emptyList := []*roadmap_content_api.EdgeInfo{}

	ownerType := roadmap_api.ROADMAP_OWNER_TYPE_ROADMAP_OWNER_ADMIN
	ownerUserId := ""

	userSess, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if ok {
		ownerType = roadmap_api.ROADMAP_OWNER_TYPE_ROADMAP_OWNER_USER
		ownerUserId = userSess.UserId
	} else {
		adminSess, ok := dao.CacheDao.GetAdminSession(ctx, req.SessionId)
		if !ok {
			return &roadmap_content_api.ListEdgeResponse{
				Code:     roadmap_content_api.ListEdgeResponse_CODE_WRONG_SESSION,
				ErrMsg:   "会话不存在",
				EdgeList: emptyList,
			}, nil
		}
		if !adminSess.AuthOk {
			return &roadmap_content_api.ListEdgeResponse{
				Code:     roadmap_content_api.ListEdgeResponse_CODE_NOT_AUTH,
				ErrMsg:   "未授权会话",
				EdgeList: emptyList,
			}, nil
		}
		adminUserCfg, err := admin_common.GetAdminUserConfig(ctx, apiImpl.adminCfg, adminSess.UserName)
		if err != nil {
			return nil, err
		}
		if !adminUserCfg.PermInfo.RoadmapPerm.Read {
			return &roadmap_content_api.ListEdgeResponse{
				Code:     roadmap_content_api.ListEdgeResponse_CODE_NO_PERMISSION,
				ErrMsg:   "没有权限",
				EdgeList: emptyList,
			}, nil
		}
		ownerType = roadmap_api.ROADMAP_OWNER_TYPE_ROADMAP_OWNER_ADMIN
		ownerUserId = adminSess.UserName
	}

	roadmapItem, err := roadmap_dao.RoadmapInfoDao.Get(ctx, req.RoadmapId)
	if err != nil {
		return &roadmap_content_api.ListEdgeResponse{
			Code:     roadmap_content_api.ListEdgeResponse_CODE_NO_ROADMAP,
			ErrMsg:   "路线图不存在",
			EdgeList: emptyList,
		}, nil
	}
	if ownerType == roadmap_api.ROADMAP_OWNER_TYPE_ROADMAP_OWNER_USER {
		//只能访问自己和公开的
		if !(roadmapItem.OwnerUserId == ownerUserId || roadmapItem.PubState) {
			return &roadmap_content_api.ListEdgeResponse{
				Code:     roadmap_content_api.ListEdgeResponse_CODE_NO_PERMISSION,
				ErrMsg:   "没有权限",
				EdgeList: emptyList,
			}, nil
		}
	}
	edgeItemList, err := roadmap_dao.EdgeDao.List(ctx, req.RoadmapId)
	if err != nil {
		return nil, err
	}
	edgeList := []*roadmap_content_api.EdgeInfo{}
	for _, edgeItem := range edgeItemList {
		edgeList = append(edgeList, edgeItem.ToEdgeInfo())
	}
	return &roadmap_content_api.ListEdgeResponse{
		Code:     roadmap_content_api.ListEdgeResponse_CODE_OK,
		EdgeList: edgeList,
	}, nil
}

func (apiImpl *RoadmapContentApiImpl) GetEdge(ctx context.Context, req *roadmap_content_api.GetEdgeRequest) (*roadmap_content_api.GetEdgeResponse, error) {
	emptyInfo := &roadmap_content_api.EdgeInfo{
		EdgeKey:   &roadmap_content_api.EdgeKey{},
		BasicInfo: &roadmap_content_api.BasicEdgeInfo{},
	}

	ownerType := roadmap_api.ROADMAP_OWNER_TYPE_ROADMAP_OWNER_ADMIN
	ownerUserId := ""

	userSess, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if ok {
		ownerType = roadmap_api.ROADMAP_OWNER_TYPE_ROADMAP_OWNER_USER
		ownerUserId = userSess.UserId
	} else {
		adminSess, ok := dao.CacheDao.GetAdminSession(ctx, req.SessionId)
		if !ok {
			return &roadmap_content_api.GetEdgeResponse{
				Code:   roadmap_content_api.GetEdgeResponse_CODE_WRONG_SESSION,
				ErrMsg: "会话不存在",
				Edge:   emptyInfo,
			}, nil
		}
		if !adminSess.AuthOk {
			return &roadmap_content_api.GetEdgeResponse{
				Code:   roadmap_content_api.GetEdgeResponse_CODE_NOT_AUTH,
				ErrMsg: "未授权会话",
				Edge:   emptyInfo,
			}, nil
		}
		adminUserCfg, err := admin_common.GetAdminUserConfig(ctx, apiImpl.adminCfg, adminSess.UserName)
		if err != nil {
			return nil, err
		}
		if !adminUserCfg.PermInfo.RoadmapPerm.Read {
			return &roadmap_content_api.GetEdgeResponse{
				Code:   roadmap_content_api.GetEdgeResponse_CODE_NO_PERMISSION,
				ErrMsg: "没有权限",
				Edge:   emptyInfo,
			}, nil
		}
		ownerType = roadmap_api.ROADMAP_OWNER_TYPE_ROADMAP_OWNER_ADMIN
		ownerUserId = adminSess.UserName
	}

	roadmapItem, err := roadmap_dao.RoadmapInfoDao.Get(ctx, req.EdgeKey.RoadmapId)
	if err != nil {
		return &roadmap_content_api.GetEdgeResponse{
			Code:   roadmap_content_api.GetEdgeResponse_CODE_NO_ROADMAP,
			ErrMsg: "路线图不存在",
			Edge:   emptyInfo,
		}, nil
	}
	if ownerType == roadmap_api.ROADMAP_OWNER_TYPE_ROADMAP_OWNER_USER {
		//只能访问自己和公开的
		if !(roadmapItem.OwnerUserId == ownerUserId || roadmapItem.PubState) {
			return &roadmap_content_api.GetEdgeResponse{
				Code:   roadmap_content_api.GetEdgeResponse_CODE_NO_PERMISSION,
				ErrMsg: "没有权限",
				Edge:   emptyInfo,
			}, nil
		}
	}
	edgeItem, err := roadmap_dao.EdgeDao.Get(ctx, req.EdgeKey.RoadmapId, &roadmap_dao.EdgeKeyDbItem{
		FromNodeId:   req.EdgeKey.FromNodeId,
		FromHandleId: req.EdgeKey.FromHandleId,
		ToNodeId:     req.EdgeKey.ToNodeId,
		ToHandleId:   req.EdgeKey.ToHandleId,
	})
	if err != nil {
		return &roadmap_content_api.GetEdgeResponse{
			Code:   roadmap_content_api.GetEdgeResponse_CODE_NO_EDGE,
			ErrMsg: "连接不存在",
			Edge:   emptyInfo,
		}, nil
	}
	return &roadmap_content_api.GetEdgeResponse{
		Code: roadmap_content_api.GetEdgeResponse_CODE_OK,
		Edge: edgeItem.ToEdgeInfo(),
	}, nil
}

func (apiImpl *RoadmapContentApiImpl) UpdateEdge(ctx context.Context, req *roadmap_content_api.UpdateEdgeRequest) (*roadmap_content_api.UpdateEdgeResponse, error) {
	ownerType := roadmap_api.ROADMAP_OWNER_TYPE_ROADMAP_OWNER_ADMIN
	ownerUserId := ""
	var roadmapPerm *admin_auth_api.RoadmapPerm
	isWhiteUser := false

	userSess, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if ok {
		ownerType = roadmap_api.ROADMAP_OWNER_TYPE_ROADMAP_OWNER_USER
		ownerUserId = userSess.UserId
		exist, err := roadmap_dao.WhiteUserDao.Exist(ctx, userSess.UserId)
		if err != nil {
			return nil, err
		}
		isWhiteUser = exist
	} else {
		adminSess, ok := dao.CacheDao.GetAdminSession(ctx, req.SessionId)
		if !ok {
			return &roadmap_content_api.UpdateEdgeResponse{
				Code:   roadmap_content_api.UpdateEdgeResponse_CODE_WRONG_SESSION,
				ErrMsg: "会话不存在",
			}, nil
		}
		if !adminSess.AuthOk {
			return &roadmap_content_api.UpdateEdgeResponse{
				Code:   roadmap_content_api.UpdateEdgeResponse_CODE_NOT_AUTH,
				ErrMsg: "未授权会话",
			}, nil
		}
		adminUserCfg, err := admin_common.GetAdminUserConfig(ctx, apiImpl.adminCfg, adminSess.UserName)
		if err != nil {
			return nil, err
		}
		if !adminUserCfg.PermInfo.RoadmapPerm.Read {
			return &roadmap_content_api.UpdateEdgeResponse{
				Code:   roadmap_content_api.UpdateEdgeResponse_CODE_NO_PERMISSION,
				ErrMsg: "没有权限",
			}, nil
		}
		ownerType = roadmap_api.ROADMAP_OWNER_TYPE_ROADMAP_OWNER_ADMIN
		ownerUserId = adminSess.UserName
		roadmapPerm = adminUserCfg.PermInfo.RoadmapPerm
	}

	roadmapItem, err := roadmap_dao.RoadmapInfoDao.Get(ctx, req.EdgeKey.RoadmapId)
	if err != nil {
		return &roadmap_content_api.UpdateEdgeResponse{
			Code:   roadmap_content_api.UpdateEdgeResponse_CODE_NO_ROADMAP,
			ErrMsg: "路线图不存在",
		}, nil
	}
	userPerm := apiImpl.calcUserPerm(roadmapItem, ownerType, ownerUserId, roadmapPerm, isWhiteUser)
	if !userPerm.CanUpdateContent {
		return &roadmap_content_api.UpdateEdgeResponse{
			Code:   roadmap_content_api.UpdateEdgeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	//检查连接是否存在
	exist, err := roadmap_dao.EdgeDao.Exist(ctx, req.EdgeKey.RoadmapId, &roadmap_dao.EdgeKeyDbItem{
		FromNodeId:   req.EdgeKey.FromNodeId,
		FromHandleId: req.EdgeKey.FromHandleId,
		ToNodeId:     req.EdgeKey.ToNodeId,
		ToHandleId:   req.EdgeKey.ToHandleId,
	})
	if err != nil {
		return nil, err
	}
	if !exist {
		return &roadmap_content_api.UpdateEdgeResponse{
			Code:   roadmap_content_api.UpdateEdgeResponse_CODE_NO_EDGE,
			ErrMsg: "连接不存在",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = roadmap_dao.EdgeDao.UpdateBasicInfo(sessCtx, req.EdgeKey.RoadmapId, &roadmap_dao.EdgeKeyDbItem{
			FromNodeId:   req.EdgeKey.FromNodeId,
			FromHandleId: req.EdgeKey.FromHandleId,
			ToNodeId:     req.EdgeKey.ToNodeId,
			ToHandleId:   req.EdgeKey.ToHandleId,
		}, &roadmap_dao.BasicEdgeInfoDbItem{
			EdgeType:      uint32(req.BasicInfo.EdgeType),
			EdgeColor:     req.BasicInfo.EdgeColor,
			HasBeginArrow: req.BasicInfo.HasBeginArrow,
			HasEndArrow:   req.BasicInfo.HasEndArrow,
			EdgeWidth:     req.BasicInfo.EdgeWidth,
		})
		if err != nil {
			return nil, err
		}
		return &roadmap_content_api.UpdateEdgeResponse{
			Code: roadmap_content_api.UpdateEdgeResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*roadmap_content_api.UpdateEdgeResponse), nil
}

func (apiImpl *RoadmapContentApiImpl) RemoveEdge(ctx context.Context, req *roadmap_content_api.RemoveEdgeRequest) (*roadmap_content_api.RemoveEdgeResponse, error) {
	ownerType := roadmap_api.ROADMAP_OWNER_TYPE_ROADMAP_OWNER_ADMIN
	ownerUserId := ""
	var roadmapPerm *admin_auth_api.RoadmapPerm
	isWhiteUser := false

	userSess, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if ok {
		ownerType = roadmap_api.ROADMAP_OWNER_TYPE_ROADMAP_OWNER_USER
		ownerUserId = userSess.UserId
		exist, err := roadmap_dao.WhiteUserDao.Exist(ctx, userSess.UserId)
		if err != nil {
			return nil, err
		}
		isWhiteUser = exist
	} else {
		adminSess, ok := dao.CacheDao.GetAdminSession(ctx, req.SessionId)
		if !ok {
			return &roadmap_content_api.RemoveEdgeResponse{
				Code:   roadmap_content_api.RemoveEdgeResponse_CODE_WRONG_SESSION,
				ErrMsg: "会话不存在",
			}, nil
		}
		if !adminSess.AuthOk {
			return &roadmap_content_api.RemoveEdgeResponse{
				Code:   roadmap_content_api.RemoveEdgeResponse_CODE_NOT_AUTH,
				ErrMsg: "未授权会话",
			}, nil
		}
		adminUserCfg, err := admin_common.GetAdminUserConfig(ctx, apiImpl.adminCfg, adminSess.UserName)
		if err != nil {
			return nil, err
		}
		if !adminUserCfg.PermInfo.RoadmapPerm.Read {
			return &roadmap_content_api.RemoveEdgeResponse{
				Code:   roadmap_content_api.RemoveEdgeResponse_CODE_NO_PERMISSION,
				ErrMsg: "没有权限",
			}, nil
		}
		ownerType = roadmap_api.ROADMAP_OWNER_TYPE_ROADMAP_OWNER_ADMIN
		ownerUserId = adminSess.UserName
		roadmapPerm = adminUserCfg.PermInfo.RoadmapPerm
	}

	roadmapItem, err := roadmap_dao.RoadmapInfoDao.Get(ctx, req.EdgeKey.RoadmapId)
	if err != nil {
		return &roadmap_content_api.RemoveEdgeResponse{
			Code:   roadmap_content_api.RemoveEdgeResponse_CODE_NO_ROADMAP,
			ErrMsg: "路线图不存在",
		}, nil
	}
	userPerm := apiImpl.calcUserPerm(roadmapItem, ownerType, ownerUserId, roadmapPerm, isWhiteUser)
	if !userPerm.CanUpdateContent {
		return &roadmap_content_api.RemoveEdgeResponse{
			Code:   roadmap_content_api.RemoveEdgeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	//检查连接是否存在
	exist, err := roadmap_dao.EdgeDao.Exist(ctx, req.EdgeKey.RoadmapId, &roadmap_dao.EdgeKeyDbItem{
		FromNodeId:   req.EdgeKey.FromNodeId,
		FromHandleId: req.EdgeKey.FromHandleId,
		ToNodeId:     req.EdgeKey.ToNodeId,
		ToHandleId:   req.EdgeKey.ToHandleId,
	})
	if err != nil {
		return nil, err
	}
	if !exist {
		return &roadmap_content_api.RemoveEdgeResponse{
			Code: roadmap_content_api.RemoveEdgeResponse_CODE_OK,
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = roadmap_dao.EdgeDao.Remove(sessCtx, req.EdgeKey.RoadmapId, &roadmap_dao.EdgeKeyDbItem{
			FromNodeId:   req.EdgeKey.FromNodeId,
			FromHandleId: req.EdgeKey.FromHandleId,
			ToNodeId:     req.EdgeKey.ToNodeId,
			ToHandleId:   req.EdgeKey.ToHandleId,
		})
		if err != nil {
			return nil, err
		}
		return &roadmap_content_api.RemoveEdgeResponse{
			Code: roadmap_content_api.RemoveEdgeResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*roadmap_content_api.RemoveEdgeResponse), nil
}
